package org.elastic.compreplatform.crawler.core.processor;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.elastic.compreplatform.common.constant.ProxyEnum;
import org.elastic.compreplatform.common.constant.RespEnum;
import org.elastic.compreplatform.common.model.RespMsg;
import org.elastic.compreplatform.common.util.SeqUtil;
import org.elastic.compreplatform.common.util.SpringContextUtil;
import org.elastic.compreplatform.crawler.controller.CraIpProxyController;
import org.elastic.compreplatform.crawler.core.thread.TaskThreadPoolExecutor;
import org.elastic.compreplatform.crawler.core.thread.task.VerifyProxyThreadTask;
import org.elastic.compreplatform.crawler.model.CraIpProxy;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.ProxyConfig;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

/**
 * ClassName: IProcessor 
 * @Description: ip爬取
 * @author JornTang
 * @date 2018年2月10日
 * 可免费获取代理地址：http://www.ip181.com/ http://www.xicidaili.com/nn/
 * "https://www.xvideos.com/video9730427/miki_sato_and_young_boy_-_penetration_part_7_of_9_"
 */
public class ProxyIProcessor {
	private static Logger log = LoggerFactory.getLogger(ProxyIProcessor.class);
	private static CraIpProxyController proxyController = SpringContextUtil.getBean(CraIpProxyController.class);
	public static void main(String[] args) {
		String url = "http://www.xicidaili.com/nn/";
		jsoup(url);
	}
	/**
	 * @Description: 使用jsoup抓取网页
	 * @param url   
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月10日
	 */
	public static void jsoup(String url){
		try {
			 //从一个网站获取和解析一个HTML文档，jsoup的API中有此方法的说明  
	        Document document = Jsoup.connect(url).proxy("139.224.135.94", 80).get();  
	        System.out.println(document);  
	        //获取所有的img标签  
	        Elements elements = document.getElementsByTag("td");  
	        for(Element element : elements){  
	            //获取每个img标签的src属性的内容，即图片地址，加"abs:"表示绝对路径  
	            String imgSrc = element.outerHtml();  
	            System.out.println(imgSrc);  
	        }  
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	/**
	 * @Description: htmlunit抓取网页
	 * @param url   
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月10日
	 */
	public static void htmlunit(String url, String type){
		//获取响应时间最短的代理
		CraIpProxy proxy = proxyController.findOptimalProxy();
		// 1创建WebClient
		WebClient webClient=new WebClient(BrowserVersion.CHROME);
		try {
			// 2 启动JS
	         webClient.getOptions().setJavaScriptEnabled(true);
	        // 3 禁用Css，可避免自动二次請求CSS进行渲染
	         webClient.getOptions().setCssEnabled(false);
	        // 4 启动客戶端重定向
	         webClient.getOptions().setRedirectEnabled(true);
	        // 5 js运行错誤時，是否拋出异常
	         webClient.getOptions().setThrowExceptionOnScriptError(false);
	        // 6 设置超时
	         webClient.getOptions().setTimeout(3*60*1000);
	         //设置代理
	         if(proxy != null){
	        	 ProxyConfig proxyConfig = webClient.getOptions().getProxyConfig();   
		         proxyConfig.setProxyHost(proxy.getProxyIp());  
		         proxyConfig.setProxyPort(proxy.getProxyPort());  
	         }
	         
	         //获取网页
	         HtmlPage htmlPage = webClient.getPage(url);
	        // 等待JS驱动dom完成获得还原后的网页
	          webClient.waitForBackgroundJavaScript(10000);
	        // 网页內容
	        Document doc=Jsoup.parse(htmlPage.asXml());
	        //抓取代理ip
	        if(ProxyEnum.IP181.getType().equals(type)){
	        	ip181Analy(doc);
	        }else if(ProxyEnum.XICIDAILI.getType().equals(type)){
	        	xicidailiAnaly(doc);
	        	//递归获取xicidaili免费IP地址
	        	String proxyUrl = doHandleUrl(url);
	        	if(StringUtils.isNotEmpty(proxyUrl)){
	        		htmlunit(proxyUrl, ProxyEnum.XICIDAILI.getType());
	        	}
	        }
		} catch (Exception e) {
			log.error("htmlunit抓取网页异常", e);
		}finally{
			//关闭windows，释放资源
			if(webClient != null){
				 webClient.closeAllWindows();
			}
		}
	}
	/**
	 * @Description: 
	 * @return   
	 * @return String  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月11日
	 */
	private static String doHandleUrl(String url) {
		if(StringUtils.isNotEmpty(url)){
			int i = url.lastIndexOf("/");
			String pagenum= url.substring(i+1, url.length());
			if(StringUtils.isEmpty(pagenum)){
				return url+"2";
			}else{
				Integer _pagenum = Integer.valueOf(pagenum);
				if(_pagenum<= 2706){
					return ProxyEnum.XICIDAILI.getUrl()+(_pagenum+1);
				}
			}
		}
		return null;
	}
	/**
	 * @Description: 抓取ip81免费代理IP
	 * @param doc   
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月10日
	 */
	public static void ip181Analy(Document doc){
		if(doc!= null){
			//查找tbody 下所有的tr标签
			Elements elements = doc.select("tbody > tr");
			if(elements.size()> 1)
			for (int i = 1; i < elements.size(); i++) {
				Element trElement = elements.get(i);
				Elements tdElements = trElement.select("td");
				CraIpProxy proxy = new CraIpProxy();
				proxy.setId(SeqUtil.getSeq());
				proxy.setProxyIp(StringUtils.trim(tdElements.get(0).text()));
				proxy.setProxyPort(Integer.valueOf(StringUtils.trim(tdElements.get(1).text())));
				proxy.setCrypLevel(StringUtils.trim(tdElements.get(2).text()));
				proxy.setProxyType(StringUtils.trim(tdElements.get(3).text()));
				float respTime = Float.valueOf(StringUtils.trim(tdElements.get(4).text().replace("秒", "")));
				//过滤掉响应时间大于1秒的IP地址
				if(respTime> 1F){
					continue;
				}
				proxy.setRespTime(respTime);
				proxy.setCityAddress(StringUtils.trim(tdElements.get(5).text()));
				proxy.setVerifyLastTime(new Date());
				proxy.setCreatTime(new Date());
				proxy.setProxyFrom("www.ip181.com免费代理网站");
				//判断ip、地址是否已经存在
				if(!ifExists(proxy)){
					//采用线程池校验IP地址有效性
					VerifyProxyThreadTask varufyTask = new VerifyProxyThreadTask(proxy);
					TaskThreadPoolExecutor.addTaskToThreadPool(varufyTask);
				}
			}
		}
	}
	/**
	 * @Description: 抓取xicidaili免费代理IP
	 * @param doc   
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月10日
	 */
	public static void xicidailiAnaly(Document doc){
		if(doc!= null){
			//查找tbody 下所有的tr标签
			Elements elements = doc.select("tbody > tr");
			if(elements.size()> 1)
			for (int i = 1; i < elements.size(); i++) {
				Element trElement = elements.get(i);
				Elements tdElements = trElement.select("td");
				CraIpProxy proxy = new CraIpProxy();
				proxy.setId(SeqUtil.getSeq());
				proxy.setProxyIp(StringUtils.trim(tdElements.get(1).text()));
				proxy.setProxyPort(Integer.valueOf(StringUtils.trim(tdElements.get(2).text())));
				proxy.setCrypLevel(StringUtils.trim(tdElements.get(4).text()));
				proxy.setProxyType(StringUtils.trim(tdElements.get(5).text()));
				float respTime = Float.valueOf(StringUtils.trim(tdElements.get(6).select("div").first().attr("title").replace("秒", "")));
				//过滤掉响应时间大于1秒的IP地址
				if(respTime> 1F){
					continue;
				}
				proxy.setRespTime(respTime);
				String cityAddress = StringUtils.trim(tdElements.get(3).select("a").text());
				proxy.setCityAddress(StringUtils.isNotEmpty(cityAddress)?cityAddress : "未知");
				proxy.setVerifyLastTime(new Date());
				proxy.setCreatTime(new Date());
				proxy.setProxyFrom("www.xicidaili.com免费代理网站");
				//判断ip、地址是否已经存在
				if(!ifExists(proxy)){
					//采用线程池校验IP地址有效性
					VerifyProxyThreadTask varufyTask = new VerifyProxyThreadTask(proxy);
					TaskThreadPoolExecutor.addTaskToThreadPool(varufyTask);
				}
			}
		}
	}
	private static boolean ifExists(CraIpProxy proxy) {
		RespMsg result = proxyController.findListByItem(proxy);
		if(RespEnum.SUCCESS.getCode().equals(result.getCode())){
			return true;
		}
		return false;
	}
	/**
	 * @Description: 过滤有效性的代理IP
	 * @param offoset
	 * @param pageSize
	 * @param mult
	 * @throws Exception   
	 * @return void  
	 * @throws
	 * @author JornTang
	 * @date 2018年2月11日
	 */
	public static void verifyProxy(int offoset, int pageSize, int mult)throws Exception{
		//获取代理集合
		List<CraIpProxy> cras = proxyController.findPageList(offoset, pageSize);
		if(cras!= null && cras.size()> 0){
			for (int i = 0; i < cras.size(); i++) {
				//采用线程池校验IP地址有效性
				CraIpProxy proxy = cras.get(i);
				proxy.setProxyType("verify");
				VerifyProxyThreadTask varufyTask = new VerifyProxyThreadTask(proxy);
				TaskThreadPoolExecutor.addTaskToThreadPool(varufyTask);
			}
			int mults = ++mult;
			verifyProxy(pageSize+1, pageSize*mults, mults);
		}
	}
}
